using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace FiveChess
{

    public enum GameType
    {
        HumanToHuman,
        HumanToComputer,
        Online
    }

    public enum GameStatus
    {
        Executing,
        Waiting

    }

    class Game:IGameInterface , IDrawScreen 
    {

        private int             stepNumber=0;
        private Stack<Chessman> chessMember = new Stack<Chessman>();
        private IDrawScreen     pIDraw=null;
        private Chessman        tmpObj = null;
        private GameType        gameType = GameType.HumanToHuman;
        private GameStatus      gameStatus = GameStatus.Executing;
        private Pen             blackPen = new Pen(Color.Green, 3);
        public event            GameStatusHandle StatusChanged;

        private IPlayer       pPlayer=null;

        private int[,] blackChess = new int[15, 15];
        private int[,] whiteChess = new int[15, 15];
        private int[,] arrayChess = new int[15, 15];


        public GameType Type
        {
            get
            {
                return gameType;
            }

            set
            {
                gameType = value;
            }      
        }

        public GameStatus Status
        {
            get
            {
                return gameStatus;
            }

            set
            {
                gameStatus = value;
            }
        }

        public IPlayer AIPlayer
        {
            get
            {
                return pPlayer;
            }

            set
            {
                pPlayer = value;
                pPlayer.playerEvent  += new PlayerEventHandle(GotNewPosition);
            }
        }

        public Game(){}

        /// <summary>
        /// Raise event Gameover  to parent
        /// </summary>
        /// <param name="e">The result message </param>
        protected virtual void FireGameStatusChanged(StatusChangedEventArgs e)
        {
            if (StatusChanged != null)
                StatusChanged(this, e);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="drawingSurface"></param>
        void IDrawScreen.Draw(Graphics drawingSurface)
        {
            foreach (Chessman member in chessMember)
            {
                if (member != null)
                {
                    pIDraw = member;
                    pIDraw.Draw(drawingSurface);
                }

                //Draw last step Mark
                tmpObj = chessMember.Peek();
                if (tmpObj != null)
                {
                    // Create rectangle for ellipse.
                    Rectangle rect = new Rectangle((tmpObj.ChessPoint.X + 1) * PublicConfigParameter.ChessmanImageLen, (tmpObj.ChessPoint.Y + 1) * PublicConfigParameter.ChessmanImageLen, 5, 5);
                    // Draw ellipse to screen.
                    drawingSurface.DrawEllipse(blackPen, rect);
                    tmpObj = null;
                }
            }
        }

        /// <summary>
        /// Check whether the target positoin already has chessman
        /// </summary>
        /// <param name="pPoint">The traget positon</param>
        /// <returns></returns>
        private bool CheckedValidity(Point pPoint)
        {
            //whether current chessman is out of board
            if (pPoint.X > 14 || pPoint.Y > 14)
            {
                return false;
            }
            //whether have chessman in same position
            foreach (Chessman member in chessMember)
            {
                if ((member != null) && (member.ChessPoint == pPoint))
                    return false;
            }
            return true;
        
        }

        private bool Add(ChessmanType pType, Point pPoint)
        {
            if (CheckedValidity(pPoint))
            {
                Chessman newChessMan;
                newChessMan = new Chessman(pType, pPoint);
                newChessMan.StepNumber = stepNumber;
                stepNumber = stepNumber + 1;
                chessMember.Push(newChessMan);
                CheckGameOver(pType, pPoint);
                return true;
            }
            else
                return false;
        }


        /// <summary>
        /// Add chessman to stack
        /// </summary>
        /// <param name="pType">chessman type </param>
        /// <param name="pPoint">chessman position </param>
        /// <returns></returns>
        bool IGameInterface.AddChessman(ChessmanType pType,Point pPoint)
        {

            if (gameStatus != GameStatus.Executing)
                return false ;

            if (Add(pType, pPoint))
            {
                if (gameType != GameType.HumanToHuman && pPlayer != null)
                {
                    pPlayer.GetNextChessmanPosition(pPoint);
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Undo the last opration
        /// </summary>
        void IGameInterface.Undo()
        {
            if (chessMember.Count > 0)
            {
                tmpObj=chessMember.Pop();
                stepNumber = stepNumber - 1;
                if (tmpObj.ChessType  == ChessmanType.Black)
                {
                    blackChess[tmpObj.ChessPoint.X, tmpObj.ChessPoint.Y] = 0;
                }
                if (tmpObj.ChessType == ChessmanType.White)
                {
                    whiteChess[tmpObj.ChessPoint.X, tmpObj.ChessPoint.Y] = 0;
                }
                tmpObj = null;

            }
        }

        private void CheckGameOver(ChessmanType pType, Point pPoint)
        {

            int i, j, iSumA, iSumB;

            System.Array.Clear(arrayChess, 0, 15 * 15);

            if (pType == ChessmanType.Black)
            {
                blackChess[pPoint.X, pPoint.Y] = 1;
                arrayChess = (int [,])blackChess.Clone();
            }
            if (pType == ChessmanType.White)
            {
                whiteChess[pPoint.X, pPoint.Y] = 1;
                arrayChess = (int[,])whiteChess.Clone();
            }

            for (i = 0; i < 15; i++)
            {
                iSumA = 0;
                iSumB = 0;
                for (j = 0; j < 15; j++)
                {
                    if (arrayChess[i, j] == 0)
                    {
                        iSumA = 0;
                    }
                    if (arrayChess[j, i] == 0)
                    {
                        iSumB = 0;
                    }
                    iSumA = iSumA + arrayChess[i, j];
                    iSumB = iSumB + arrayChess[j, i];
                    if (iSumA >= 5 || iSumB >= 5)
                    {
                        StatusChangedEventArgs fireArgs= new StatusChangedEventArgs(pType.ToString());
                        FireGameStatusChanged(fireArgs);
                        return;
                    }

                }
            }

            int[] iTotalA = new int[30];
            int[] iTotalB = new int[30];
            for (i = 0; i < 15; i++)
            {
                for (j = 0; j < 15; j++)
                {
                        if (arrayChess[i, j] == 0)
                        {
                            iTotalA[j - i + 15] = 0;
                        }
                        if (arrayChess[i,j] == 0)
                        {
                            iTotalB[i + j ] = 0;
                        }
                        iTotalA[j - i + 15] = iTotalA[j - i + 15] + arrayChess[i, j];
                        iTotalB[i + j] = iTotalB[i+j] + arrayChess[i,j];
                        if (iTotalA[j - i + 15] >= 5 || iTotalB[i+j]>=5)
                        {
                            StatusChangedEventArgs fireArgs = new StatusChangedEventArgs(pType.ToString());
                            FireGameStatusChanged(fireArgs);
                            return;

                        }

                }
            }


        }

        private void GotNewPosition(object sender, PlayerEventArgs e)
        {
            
            gameStatus = GameStatus.Executing;
            Add(ChessmanType.White  , e.position);
            StatusChangedEventArgs fireArgs= new StatusChangedEventArgs("aa");
            FireGameStatusChanged(fireArgs);
        }

    }
}
